package com.ccrfid.rmc6.service.open;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.personnel.*;
import com.ccrfid.rmc6.entity.poi.PoiLocationEntity;
import com.ccrfid.rmc6.entity.video.VideoCameraView;
import com.ccrfid.rmc6.pojo.dto.open2.CardHeartRateDto;
import com.ccrfid.rmc6.pojo.dto.open2.LocatePositionDto;
import com.ccrfid.rmc6.pojo.dto.open2.LocationDto;
import com.ccrfid.rmc6.pojo.dto.open2.OpenPersonnelDto;
import com.ccrfid.rmc6.repository.device.CardRepository;
import com.ccrfid.rmc6.repository.personnel.*;
import com.ccrfid.rmc6.repository.poi.PoiLocationRepository;
import com.ccrfid.rmc6.service.poi.PoiService;
import org.hibernate.query.NativeQuery;
import org.hibernate.spatial.JTSGeometryType;
import org.hibernate.spatial.dialect.mysql.MySQLGeometryTypeDescriptor;
import org.hibernate.transform.Transformers;
import org.hibernate.type.IntegerType;
import org.hibernate.type.LongType;
import org.hibernate.type.StringType;
import org.hibernate.type.TimestampType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
public class OpenV2ServiceImpl implements OpenV2Service {

    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private PersonnelRepository personnelRepository;
    @Autowired
    private PoiLocationRepository poiLocationRepository;
    @Autowired
    private CardRepository cardRepository;
    @Autowired
    private PersonnelHeartRateRepository personnelHeartRateRepository;
    @Autowired
    private PersonnelStepTrackRepository personnelStepTrackRepository;
    @Autowired
    private PersonnelBloodPressureRepository bloodPressureRepository;
    @Autowired
    private PersonnelTemperatureRepository temperatureRepository;
    @Autowired
    private PoiService poiService;

    @Override
    public List<OpenPersonnelDto> getAllPersonnel() {
        String sql = "SELECT p.id as personnelId, p.personnel_name as personnelName, p.card_number as cardNumber, " +
                " p.personnel_sn as personnelSn, p.personnel_type as personnelType, d.dict_name as personnelTypeName, " +
                " p.gender, o.id as orgId, o.org_name as orgName, o.org_sn as orgSn " +
                " FROM personnel p " +
                " left join s_org o on p.org_id = o.id " +
                " left join s_dict d on p.personnel_type = d.id " +
                " WHERE p.is_enabled = 1";
        List<OpenPersonnelDto> list = entityManager.createNativeQuery(sql)
                .unwrap(NativeQuery.class)
                .addScalar("personnelId", LongType.INSTANCE)
                .addScalar("personnelName", StringType.INSTANCE)
                .addScalar("cardNumber", LongType.INSTANCE)
                .addScalar("personnelSn", StringType.INSTANCE)
                .addScalar("personnelType", IntegerType.INSTANCE)
                .addScalar("personnelTypeName", StringType.INSTANCE)
                .addScalar("gender", IntegerType.INSTANCE)
                .addScalar("orgId", LongType.INSTANCE)
                .addScalar("orgName", StringType.INSTANCE)
                .addScalar("orgSn", StringType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(OpenPersonnelDto.class))
                .list();
        return list;
    }

    @Override
    public OpenPersonnelDto getPersonnelBySn(String personnelSn) throws AppException {
        if (personnelSn == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        if (!personnelRepository.existsByPersonnelSn(personnelSn)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        String sql = "SELECT p.id as personnelId, p.personnel_name as personnelName, p.card_number as cardNumber, " +
                " p.personnel_sn as personnelSn, p.personnel_type as personnelType, d.dict_name as personnelTypeName, " +
                " p.gender, o.id as orgId, o.org_name as orgName, o.org_sn as orgSn " +
                " FROM personnel p " +
                " left join s_org o on p.org_id = o.id " +
                " left join s_dict d on p.personnel_type = d.id " +
                " WHERE p.personnel_sn = :psn";
        List<OpenPersonnelDto> list = entityManager.createNativeQuery(sql)
                .setParameter("psn", personnelSn)
                .unwrap(NativeQuery.class)
                .addScalar("personnelId", LongType.INSTANCE)
                .addScalar("personnelName", StringType.INSTANCE)
                .addScalar("cardNumber", LongType.INSTANCE)
                .addScalar("personnelSn", StringType.INSTANCE)
                .addScalar("personnelType", IntegerType.INSTANCE)
                .addScalar("personnelTypeName", StringType.INSTANCE)
                .addScalar("gender", IntegerType.INSTANCE)
                .addScalar("orgId", LongType.INSTANCE)
                .addScalar("orgName", StringType.INSTANCE)
                .addScalar("orgSn", StringType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(OpenPersonnelDto.class))
                .list();
        if (list != null && list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    @Override
    public OpenPersonnelDto getPersonnelById(Long personnelId) throws AppException {
        if (personnelId == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        if (!personnelRepository.existsById(personnelId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        String sql = "SELECT p.id as personnelId, p.personnel_name as personnelName, p.card_number as cardNumber, " +
                " p.personnel_sn as personnelSn, p.personnel_type as personnelType, d.dict_name as personnelTypeName, " +
                " p.gender, o.id as orgId, o.org_name as orgName, o.org_sn as orgSn " +
                " FROM personnel p " +
                " left join s_org o on p.org_id = o.id " +
                " left join s_dict d on p.personnel_type = d.id " +
                " WHERE p.id = :pid";
        List<OpenPersonnelDto> list = entityManager.createNativeQuery(sql)
                .setParameter("pid", personnelId)
                .unwrap(NativeQuery.class)
                .addScalar("personnelId", LongType.INSTANCE)
                .addScalar("personnelName", StringType.INSTANCE)
                .addScalar("cardNumber", LongType.INSTANCE)
                .addScalar("personnelSn", StringType.INSTANCE)
                .addScalar("personnelType", IntegerType.INSTANCE)
                .addScalar("personnelTypeName", StringType.INSTANCE)
                .addScalar("gender", IntegerType.INSTANCE)
                .addScalar("orgId", LongType.INSTANCE)
                .addScalar("orgName", StringType.INSTANCE)
                .addScalar("orgSn", StringType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(OpenPersonnelDto.class))
                .list();
        if (list != null && list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    @Override
    public LocatePositionDto getPersonnelLocatePosition(String personnelSn) throws AppException {
        if (personnelSn == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        if (!personnelRepository.existsByPersonnelSn(personnelSn)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        String sql = "SELECT p.id as locationId, p.location_name as locationName, p.location_sn as locationSn, v.floor_number as floorNumber, " +
                " v.locator_address as locatorAddress, v.pos, v.last_locate_time as locateTime " +
                " FROM v_personnel v " +
                " left join poi_location p on p.map_level = 3 and p.floor_number = v.floor_number and st_contains(p.location_polygon, v.pos) " +
                " where v.personnel_sn = :psn";
        List<LocatePositionDto> list = entityManager.createNativeQuery(sql)
                .setParameter("psn", personnelSn)
                .unwrap(NativeQuery.class)
                .addScalar("locationId", LongType.INSTANCE)
                .addScalar("locationName", StringType.INSTANCE)
                .addScalar("locationSn", StringType.INSTANCE)
                .addScalar("floorNumber", IntegerType.INSTANCE)
                .addScalar("locatorAddress", IntegerType.INSTANCE)
                .addScalar("pos", new JTSGeometryType(MySQLGeometryTypeDescriptor.INSTANCE))
                .addScalar("locateTime", TimestampType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(LocatePositionDto.class))
                .list();
        if (list != null && list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    @Override
    public LocatePositionDto getPersonnelLocatePosition(Long personnelId) throws AppException {
        PersonnelEntity personnel = personnelRepository.getById(personnelId);
        if (personnel != null) {
            return getPersonnelLocatePosition(personnel.getPersonnelSn());
        } else {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
    }

    @Override
    public List<LocatePositionDto> getPersonnelLocatePositionRecords(String personnelSn,
                                                                     Timestamp startTime, Timestamp stopTime)
            throws AppException {
        if (personnelSn == null || startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        PersonnelEntity personnelEntity = personnelRepository.getByPersonnelSn(personnelSn);
        if (personnelEntity == null) {
            if (!personnelRepository.existsByPersonnelSn(personnelSn)) {
                throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                        CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
            }
        }
        String sql = "SELECT p.id as locationId, p.location_name as locationName, p.floor_number as floorNumber, p.location_sn as locationSn, " +
                " m.current_locator_address as locatorAddress, POINT(m.current_x, m.current_y) as pos, m.record_time as locateTime " +
                " FROM personnel_move m " +
                " left join poi_location p on p.map_level = 3 and p.floor_number = m.current_floor_number " +
                " and st_contains(p.location_polygon, POINT(m.current_x, m.current_y)) " +
                " where m.personnel_id = :perId and (m.record_time between :startT and :stopT)" +
                " order by m.id asc ";
        List<LocatePositionDto> list = entityManager.createNativeQuery(sql)
                .setParameter("perId", personnelEntity.getId())
                .setParameter("startT", startTime)
                .setParameter("stopT", stopTime)
                .unwrap(NativeQuery.class)
                .addScalar("locationId", LongType.INSTANCE)
                .addScalar("locationName", StringType.INSTANCE)
                .addScalar("locationSn", StringType.INSTANCE)
                .addScalar("floorNumber", IntegerType.INSTANCE)
                .addScalar("locatorAddress", IntegerType.INSTANCE)
                .addScalar("pos", new JTSGeometryType(MySQLGeometryTypeDescriptor.INSTANCE))
                .addScalar("locateTime", TimestampType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(LocatePositionDto.class))
                .list();
        return list;
    }

    @Override
    public List<LocationDto> getAllLocationsByMapLevel(Integer mapLevel) {
        String sql = "SELECT id as locationId, location_name as locationName, location_centroid as locationCentroid, " +
                " location_polygon as locationPolygon, location_sn as locationSn, floor_number as floorNumber, map_level as mapLevel " +
                " FROM poi_location where map_level = " + mapLevel;
        List<LocationDto> list = entityManager.createNativeQuery(sql)
                .unwrap(NativeQuery.class)
                .addScalar("locationId", LongType.INSTANCE)
                .addScalar("locationName", StringType.INSTANCE)
                .addScalar("locationCentroid", new JTSGeometryType(MySQLGeometryTypeDescriptor.INSTANCE))
                .addScalar("locationPolygon", new JTSGeometryType(MySQLGeometryTypeDescriptor.INSTANCE))
                .addScalar("locationSn", StringType.INSTANCE)
                .addScalar("floorNumber", IntegerType.INSTANCE)
                .addScalar("mapLevel", IntegerType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(LocationDto.class))
                .list();
        return list;
    }

    @Override
    public List<OpenPersonnelDto> getPersonnelInLocationById(Long locationId) throws AppException {
        if (locationId == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        PoiLocationEntity locationEntity = poiLocationRepository.getById(locationId);
        if (locationEntity == null) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        String sql = "SELECT v.id as personnelId, v.personnel_name as personnelName, v.card_number as cardNumber, " +
                " v.personnel_sn as personnelSn, v.personnel_type as personnelType, v.personnel_type_name as personnelTypeName, " +
                " v.gender, o.id as orgId, o.org_name as orgName, o.org_sn as orgSn " +
                " FROM v_personnel v " +
                " left join s_org o on v.org_id = o.id " +
                " left join poi_location p on p.map_level = :mapLevel and p.floor_number = v.floor_number and st_contains(p.location_polygon, v.pos) " +
                "    where p.id = :locId";
        List<OpenPersonnelDto> list = entityManager.createNativeQuery(sql)
                .setParameter("mapLevel", locationEntity.getMapLevel())
                .setParameter("locId", locationId)
                .unwrap(NativeQuery.class)
                .addScalar("personnelId", LongType.INSTANCE)
                .addScalar("personnelName", StringType.INSTANCE)
                .addScalar("cardNumber", LongType.INSTANCE)
                .addScalar("personnelSn", StringType.INSTANCE)
                .addScalar("personnelType", IntegerType.INSTANCE)
                .addScalar("personnelTypeName", StringType.INSTANCE)
                .addScalar("gender", IntegerType.INSTANCE)
                .addScalar("orgId", LongType.INSTANCE)
                .addScalar("orgName", StringType.INSTANCE)
                .addScalar("orgSn", StringType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(OpenPersonnelDto.class))
                .list();
        return list;
    }

    @Override
    public List<OpenPersonnelDto> getPersonnelInLocationBySn(String locationSn) throws AppException {
        if (StringUtils.isEmpty(locationSn)) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        PoiLocationEntity locationEntity = poiLocationRepository.getByLocationSn(locationSn);
        if (locationEntity == null) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        String sql = "SELECT v.id as personnelId, v.personnel_name as personnelName, v.card_number as cardNumber, " +
                " v.personnel_sn as personnelSn, v.personnel_type as personnelType, v.personnel_type_name as personnelTypeName, " +
                " v.gender, o.id as orgId, o.org_name as orgName, o.org_sn as orgSn " +
                " FROM v_personnel v " +
                " left join s_org o on v.org_id = o.id " +
                " left join poi_location p on p.map_level = :mapLevel and p.floor_number = v.floor_number and st_contains(p.location_polygon, v.pos) " +
                "    where p.location_sn = :locSn";
        List<OpenPersonnelDto> list = entityManager.createNativeQuery(sql)
                .setParameter("mapLevel", locationEntity.getMapLevel())
                .setParameter("locSn", locationSn)
                .unwrap(NativeQuery.class)
                .addScalar("personnelId", LongType.INSTANCE)
                .addScalar("personnelName", StringType.INSTANCE)
                .addScalar("cardNumber", LongType.INSTANCE)
                .addScalar("personnelSn", StringType.INSTANCE)
                .addScalar("personnelType", IntegerType.INSTANCE)
                .addScalar("personnelTypeName", StringType.INSTANCE)
                .addScalar("gender", IntegerType.INSTANCE)
                .addScalar("orgId", LongType.INSTANCE)
                .addScalar("orgName", StringType.INSTANCE)
                .addScalar("orgSn", StringType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(OpenPersonnelDto.class))
                .list();
        return list;
    }

    @Override
    public List<String> getCameraIdListInLocation(Long locationId) {
        List<String> idList = new ArrayList<>();
        PoiLocationEntity locationEntity = poiLocationRepository.getById(locationId);
        if (locationEntity != null) {
            List<VideoCameraView> list = poiService.getCamerasInLocation(locationEntity);
            if (list != null && list.size() > 0) {
                list.forEach(camera -> idList.add(camera.getCameraSn()));
            }
        }
        return idList;
    }

    @Override
    public Integer getStepCountByCardNumber(Long cardNumber, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!cardRepository.existsByCardNumber(cardNumber)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        List<PersonnelStepTrackEntity> trackList =
                personnelStepTrackRepository.getAllByCardNumberAndRecordTimeBetween(cardNumber, startTime, stopTime);
        if (trackList != null && trackList.size() > 1) {
            List<Integer> stepList = new ArrayList<>();
            for (int i = 0; i < trackList.size() - 1; i++) {
                int left = trackList.get(i).getStepCount();
                int right = trackList.get(i + 1).getStepCount();
                if (right >= left) {
                    stepList.add(right - left);
                } else {
                    //stepList.add(65535 + right - left);
                    stepList.add(right);    //标签断电重启会造成计数归0，不会到达65535
                }
            }
            Optional<Integer> result = stepList.stream().reduce((a, b) -> a + b);
            if (result.isPresent()) {
                return result.get();
            } else {
                return 0;
            }
        } else {
            return 0;
        }
    }

    @Override
    public Integer getStepCountByPersonnelId(Long personnelId, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!personnelRepository.existsById(personnelId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        List<PersonnelStepTrackEntity> trackList =
                personnelStepTrackRepository.getAllByPersonnelIdAndRecordTimeBetween(personnelId, startTime, stopTime);
        if (trackList != null && trackList.size() > 1) {
            List<Integer> stepList = new ArrayList<>();
            for (int i = 0; i < trackList.size() - 1; i++) {
                int left = trackList.get(i).getStepCount();
                int right = trackList.get(i + 1).getStepCount();
                if (right >= left) {
                    stepList.add(right - left);
                } else {
                    //stepList.add(65535 + right - left);
                    stepList.add(right);    //标签断电重启会造成计数归0，不会到达65535
                }
            }
            Optional<Integer> result = stepList.stream().reduce((a, b) -> a + b);
            if (result.isPresent()) {
                return result.get();
            } else {
                return 0;
            }
        } else {
            return 0;
        }
    }

    @Override
    public List<CardHeartRateDto> getHeartRateRecordsByCardNumber(Long cardNumber, Timestamp startTime, Timestamp stopTime)
            throws AppException {
        if (!cardRepository.existsByCardNumber(cardNumber)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }

        List<PersonnelHeartRateEntity> list =
                personnelHeartRateRepository.getAllByCardNumberAndRecordTimeBetween(cardNumber, startTime, stopTime);
        if (list != null && list.size() > 0) {
            return list.stream()
                    .map(entity -> new CardHeartRateDto(entity.getCardNumber(), entity.getHeartRate(), entity.getRecordTime()))
                    .collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public List<PersonnelHeartRateEntity> getHeartRateRecordsByPersonnelId(
            Long personnelId, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!personnelRepository.existsById(personnelId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return personnelHeartRateRepository.getAllByPersonnelIdAndRecordTimeBetween(personnelId, startTime, stopTime);
    }

    @Override
    public List<PersonnelBloodPressureEntity> getBloodPressureRecordsByCardNumber(
            Long cardNumber, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!cardRepository.existsByCardNumber(cardNumber)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return bloodPressureRepository.getAllByCardNumberAndRecordTimeBetween(cardNumber, startTime, stopTime);
    }

    @Override
    public List<PersonnelBloodPressureEntity> getBloodPressureRecordsByPersonnelId(
            Long personnelId, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!personnelRepository.existsById(personnelId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return bloodPressureRepository.getAllByPersonnelIdAndRecordTimeBetweenOrderByIdAsc(personnelId, startTime, stopTime);
    }

    @Override
    public List<PersonnelTemperatureEntity> getTemperatureRecordsByCardNumber(
            Long cardNumber, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!cardRepository.existsByCardNumber(cardNumber)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return temperatureRepository.getAllByCardNumberAndRecordTimeBetween(cardNumber, startTime, stopTime);
    }

    @Override
    public List<PersonnelTemperatureEntity> getTemperatureRecordsByPersonnelId(
            Long personnelId, Timestamp startTime, Timestamp stopTime) throws AppException {
        if (!personnelRepository.existsById(personnelId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.card_not_found.getCode(), CustomErrors.card_not_found.getReason(), "");
        }
        if (startTime == null || stopTime == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return temperatureRepository.getAllByPersonnelIdAndRecordTimeBetweenOrderByIdAsc(personnelId, startTime, stopTime);
    }
}
